#include <iostream>
#include <windows.h>
#include <ctime>
#include <conio.h>
#include <list>
#include <MMSystem.h>
#include <cstdlib>

/* */

using namespace std;

int halalszam = 0;

enum
{
	HELY,
	FAL,
	KIGYO,
	KAJA
};

struct vektor
{
	int x;
	int y;
};

void kurzor(bool lathatosag)
{
	HANDLE output_handle;
	CONSOLE_CURSOR_INFO cciInfo;

	cciInfo.dwSize = 1;
	cciInfo.bVisible = lathatosag;

	output_handle = GetStdHandle(STD_OUTPUT_HANDLE);

	SetConsoleCursorInfo(output_handle,&cciInfo);
}

void gotoxy(int x, int y)
{
	HANDLE output_handle;
	COORD pos;

	pos.X = x;
	pos.Y = y;

	output_handle = GetStdHandle(STD_OUTPUT_HANDLE);

	SetConsoleCursorPosition(output_handle, pos);
}

bool lenyom(char *c)
{
	if (kbhit())
	{
		*c = getch();
		return true;
	}
	return false;
}

// Palya ---------------------------------------------------------------------------------------------------------------------------

class Palya
{
public:
	Palya(int surusegT = 0, int hosszusagT = 80, int szelessegT = 23, char helyT = ' ', char falT = 219);
	void Torol();
	void megrajzol();
	void jatekVege();

	char **halo;
	int hosszusag;
	int szelesseg;

private:
	int suruseg;
	char hely;
	char fal;	
};

Palya::Palya(int surusegT, int hosszusagT, int szelessegT, char helyT, char falT)
{
	hosszusag = hosszusagT;
	szelesseg = szelessegT;
	suruseg = surusegT;
	hely = helyT;
	fal = falT;

	halo = new char* [hosszusag];

	for (int i = 0; i < hosszusag; i++)
		halo[i] = new char[szelesseg];
}

void Palya::Torol()
{
	for (int i = 0; i < hosszusag; i++)
		delete[] halo[i];

	delete [] halo;
}

void Palya::megrajzol()
{
	for (int i = 0 ; i < hosszusag ; i++)
	{
		for (int j = 0 ; j < szelesseg ; j++)
		{
			if ((i == 0) || (i == (hosszusag - 1)) || (j == 0) || (j == (szelesseg - 1)))
			{
				halo[i][j] = FAL;
				gotoxy(i, j);
				cout << fal;
			}
			else
			{
				if (((i == 4) && (j == 5)) || ((i == 5) && (j == 5)) || ((i == 6) && (j == 5)) ||
					((i == 7) && (j == 5)) || ((i == 8) && (j == 5)) || ((i == 9) && (j == 5)) ||
					((i == 10) && (j == 5)) || ((i == 11) && (j == 5)) || ((i == 12) && (j == 5)) ||
					((i == 3) && (j == 5)))
				{
					halo[i][j] = HELY;
					gotoxy(i, j);
					cout << hely;
				}
				else
				{
					if ((rand() % 100) < suruseg)
					{
						halo[i][j] = FAL;
						gotoxy(i, j);
						cout << fal;
					}
					else
					{
						halo[i][j] = HELY;
						gotoxy(i, j);
						cout << hely;
					}
				}
			}
		}
	}
}

void Palya::jatekVege()
{
	for (int i = 0 ; i < hosszusag ; i++)
	{
		for (int j = 0 ; j < (szelesseg + 1) ; j++)
		{
			gotoxy(i, j);
			cout << " ";
		}
	}
	
	gotoxy(0, szelesseg + 1);
	cout << "                                      Antal Szabolcs (szabolcs_antal@yahoo.com)";
		
	gotoxy(5, 3);
	cout << "A jatekot befejezted, " << halalszam << "x haltal meg.";

	gotoxy(0, szelesseg + 1);
}

// Kigyo ---------------------------------------------------------------------------------------------------------------------------

struct Kaja
{
	bool igaz;
	int x;
	int y;
};

list<vektor> lista;

class Kigyo
{
public:
	Kigyo(Palya palyaT, int etelT);

	void iranytvalt(char c);
	void lep();
	int visszaAdEtel();
	void csokkentEtel();
	void beteszEtel(int szam);
	int kezd;
	void beteszElindult(int szam);
	int visszaadElindult();

	Kaja kaja;

private:
	int hossz;
	int elet;
	int osszes;
	vektor eleje;
	vektor vege;
	vektor iranya;
	Palya palya;
	int pont;
	int etel;
	int elindult;
};

Kigyo::Kigyo(Palya palyaT, int etelT)
{
	hossz = 3;
	elet = 5;

	eleje.x = 5;
	eleje.y = 5;

	vege.x = 5;
	vege.y = 3;

	iranya.x = 1;
	iranya.y = 0;

	pont = 0;

	kezd = 0;

	etel = etelT;
	osszes = etel;

	gotoxy(15, palya.szelesseg);
	cout << "pont: " << pont << "/" << osszes;

	gotoxy(28, palya.szelesseg);
	cout << "meghalt: " << halalszam;

	palya.hosszusag = palyaT.hosszusag;
	palya.szelesseg = palyaT.szelesseg;
	
	for (int i = 0 ; i < palya.hosszusag ; i++)
		for (int j = 0 ; j < palya.szelesseg ; j++)
			palya.halo[i][j] = palyaT.halo[i][j];

	HANDLE hStdout; 
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

	SetConsoleTextAttribute(hStdout, 12);
	
	for (int i = 0 ; i < 2 ; i++)
	{
		gotoxy(eleje.x - i, eleje.y);
		cout << char(219);
		palya.halo[eleje.x - i][eleje.y] = KIGYO;
	}

	SetConsoleTextAttribute(hStdout, 7);

	vektor seged;

	lista.clear();

	for (int i = 1 ; i >= 0 ; i--)
	{
		seged.x = eleje.x - i;
		seged.y = eleje.y;
		lista.push_front(seged);
	}
}

void Kigyo::iranytvalt(char c)
{
	if (c == 'w')
	{
		if (iranya.y != 1)
		{
			iranya.x = 0;
			iranya.y = -1;
		}
	}
	else
	if (c == 's')
	{
		if (iranya.y != -1)
		{
			iranya.x = 0;
			iranya.y = 1;
		}
	}
	else
	if (c == 'a')
	{
		if (iranya.x != 1)
		{
			iranya.x = -1;
			iranya.y = 0;
		}
	}
	else
	if (c == 'd')
	{
		if (iranya.x != -1)
		{
			iranya.x = 1;
			iranya.y = 0;
		}
	}
}

void Kigyo::lep()
{
	HANDLE hStdout;
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

	int start = timeGetTime();

	while (1)
		if ((timeGetTime() - start) > 100)
			break;

	if (kaja.igaz == true)
	{
		gotoxy(lista.back().x, lista.back().y);
		cout << ' ';
		palya.halo[lista.back().x][lista.back().y] = HELY;

		lista.pop_back();
	}

	if (kaja.igaz == false)
	{
		while (kaja.igaz==false)
		{
			kaja.x = 1 + rand() % (palya.hosszusag-2);
			kaja.y = 1 + rand() % (palya.szelesseg-2);

			int lehet = 0;

			if ((palya.halo[kaja.x][kaja.y] != FAL) && (palya.halo[kaja.x][kaja.y] != KIGYO))
			{
				if ((palya.halo[kaja.x+1][kaja.y] == FAL) || (palya.halo[kaja.x+1][kaja.y] == KIGYO))
					lehet++;
				if ((palya.halo[kaja.x-1][kaja.y] == FAL) || (palya.halo[kaja.x+1][kaja.y] == KIGYO))
					lehet++;
				if ((palya.halo[kaja.x][kaja.y+1] == FAL) || (palya.halo[kaja.x+1][kaja.y] == KIGYO))
					lehet++;
				if ((palya.halo[kaja.x][kaja.y-1] == FAL) || (palya.halo[kaja.x+1][kaja.y] == KIGYO))
					lehet++;
				if (lehet < 3)
					kaja.igaz = true;
			}
		}
		SetConsoleTextAttribute(hStdout, 6);

		gotoxy(kaja.x, kaja.y);
		cout << char(219);
		palya.halo[kaja.x][kaja.y] = KAJA;

		SetConsoleTextAttribute(hStdout, 7);
	}

	if ((palya.halo[eleje.x + iranya.x][eleje.y + iranya.y] == FAL) || (palya.halo[eleje.x + iranya.x][eleje.y + iranya.y] == KIGYO))
	{
		gotoxy(eleje.x + iranya.x, eleje.y + iranya.y);
		cout << "X";

		halalszam++; // Szabi

		int ido = timeGetTime();

		while (1)
		{
			if ((timeGetTime() - ido) > 500)
				break;
		}

		if (palya.halo[eleje.x + iranya.x][eleje.y + iranya.y] == FAL)
		{
			gotoxy(eleje.x + iranya.x, eleje.y + iranya.y);
			cout << char(219);
		}
		else
		{
			gotoxy(eleje.x + iranya.x, eleje.y + iranya.y);
			cout << " ";
		}

		eleje.x = 5;
		eleje.y = 5;

		gotoxy(15, palya.szelesseg);
			cout << "pont: 0/"<< osszes << "    ";

		gotoxy(28, palya.szelesseg);
			cout << "meghalt: " << halalszam; 

		pont = 0;

		for (list<vektor>::iterator i = lista.begin() ; i != lista.end(); i++)
		{
			gotoxy(i->x, i->y);
			cout << " ";
			palya.halo[i->x][i->y] = HELY;
		} 

		lista.clear();

		SetConsoleTextAttribute(hStdout, 12);
	
		for (int i = 0 ; i < 3 ; i++)
		{
			gotoxy(eleje.x - i, eleje.y);
			cout << char(219);
			palya.halo[eleje.x - i][eleje.y] = KIGYO;
		}

		SetConsoleTextAttribute(hStdout, 7);

		this->elindult = 0;
		this->etel = osszes;

		vektor seged;

		for (int i = 2 ; i >= 0 ; i--)
		{
			seged.x = eleje.x - i;
			seged.y = eleje.y;
			lista.push_front(seged);
		}

		iranya.x = 1;

		kezd = 1;
	}
	
	else
	{
		eleje.x += iranya.x;
		eleje.y += iranya.y;

		if ((eleje.x == kaja.x) && (eleje.y == kaja.y))
		{
			kaja.igaz = false;
			pont++;
			
			gotoxy(15, palya.szelesseg);
			cout << "pont: " << pont << "/" << osszes;

			gotoxy(28, palya.szelesseg);
			cout << "meghalt: " << halalszam;

			this->csokkentEtel();
		}

		lista.push_front(eleje);

		SetConsoleTextAttribute(hStdout, 12);

		gotoxy(eleje.x, eleje.y);
		cout << char(219);
		palya.halo[eleje.x][eleje.y] = KIGYO;

		SetConsoleTextAttribute(hStdout, 7);
	}
}

int Kigyo::visszaAdEtel()
{
	return etel;
}

void Kigyo::csokkentEtel()
{
	etel--;
}

void Kigyo::beteszElindult(int szam)
{
	elindult = szam;
}

int Kigyo::visszaadElindult()
{
	return elindult;
}

void Kigyo::beteszEtel(int szam)
{
	etel = szam;
}


// Jatek ---------------------------------------------------------------------------------------------------------------------------

class Jatek
{
public:
	void lefut();

private:
	Palya palya;
};

void Jatek::lefut()
{
	srand(time(NULL));

	kurzor(false);

	gotoxy(13,5);
	cout << "  A jatek celja minel kevesebb halallal vegig vinni";
	gotoxy(13,6);
	cout << "  az osszes szintet. 15 egyre nehezedo szinten kell";
	gotoxy(13,7);
	cout << " vegigmenni, melyeknek nehezsege a falak surusegeben";
	gotoxy(13,8);
	cout << "rejlik. Az aktualis szint-1 szazaleka a palyanak fal.";
	gotoxy(13,9);
	cout << "Minden szintrol 5 kaja felvetelevel lehet tovabbjutni.";
	gotoxy(13,10);
	cout << " Egy halal utan hiaba volt felveve akarhany kaja, ez";
	gotoxy(13,11);
	cout << "lenullazodik, ezzel egyidoben a kigyo hossza is a kez-";
	gotoxy(13,12);
	cout << "detire csokken, s a kigyo a kezdeti poziciojara kerul.";
	gotoxy(13,13);
	cout << "Minden kaja felvetelekor termeszetesen a kigyo hossza";
	gotoxy(13,14);
	cout << "   is no eggyel. Lehetseges halalok szama vegtelen.";
	gotoxy(13,16);
	cout << "                      Sok sikert!";
	gotoxy(13,18);	
	cout << "            keszitette: Antal Szabolcs, 521";
	gotoxy(13,19);
	cout << "                keszult: 2011. 11. 28.";
	gotoxy(13,20);
	cout << "            email: szabolcs_antal@yahoo.com";

	while (getch() != 13) {}; 

	int i, j;

	for (i = 13; i < 70; i++) // szoveg torlese
		for (j = 5; j < 21; j++)
		{
			gotoxy(i, j);
			cout << " ";
		}

	gotoxy(30,6);
	cout << "   w - fel" << endl;
	gotoxy(30,7);
	cout << "   s - le" << endl;
	gotoxy(30,8);
	cout << "   a - balra" << endl;
	gotoxy(30,9);
	cout << "   d - jobbra" << endl;
	gotoxy(30,10);
	cout << "   p - szunet" << endl;
	gotoxy(30,11);
	cout << "   q - kilep" << endl;
	gotoxy(30,13);
	cout << "ha mehet, ENTER!" << endl;

	while (getch() != 13) {}; 

	for (int i = 0; i < 15; i++)
	{
		Palya palya(i);
		palya.megrajzol();

		gotoxy(1, 23);
		cout << "szint: " << i+1 << "/15";

		gotoxy(0, palya.szelesseg + 1);
		cout << " kilepes : q   szunet : p             Antal Szabolcs (szabolcs_antal@yahoo.com)";
		
		Kigyo kigyo(palya, 5);
		kigyo.kaja.igaz = false;
		kigyo.beteszElindult(0);

		char gomb = 'd';

		kigyo.iranytvalt(gomb);
		kigyo.lep();

		bool megy = true;

		while (megy)
		{
			while (!lenyom(&gomb))
			{
				if (kigyo.visszaAdEtel() == 0)
				{
					megy = false;
					break;
				}

				if (gomb == 'q')
				{
					gotoxy(0,palya.szelesseg+1);
					exit(0);
				}
				if (gomb == 'p')
				{
					while (1)
					{
						gomb = getch();
						if ((gomb == 'w') || (gomb == 'a') || (gomb == 's') || (gomb == 'd') || (gomb == 'q'))
							break;
					}
				}
				if (kigyo.kezd == 1)
				{
					gomb = 'd';
					kigyo.kezd = 0;
				}

				if (kigyo.visszaadElindult() == 0) // halalkor megall es var
					while (1)
					{
						gomb = getch();

						if ((gomb == 'w') || (gomb == 'a') || (gomb == 's') || (gomb == 'd') || (gomb == 'q') || (gomb == 'p'))
							{
								kigyo.beteszElindult(1);
								break;
							}
					}

				kigyo.iranytvalt(gomb);
				kigyo.lep();
			}
		}

		palya.Torol();
	}

	// for utan
	palya.jatekVege();
}

int main()
{
	Jatek jatek;
	jatek.lefut();
}